GtkCssProvider: Fix parsing of concatenated classes.
authorCarlos Garnacho <carlosg@gnome.org>
Fri, 29 Oct 2010 03:30:36 +0000 (05:30 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Sat, 4 Dec 2010 14:38:29 +0000 (15:38 +0100)
Now selectors such as:

 GtkWidget#name.class1.class2
 #name.class1.class2
 .class1.class2

are parsed correctly, being meaningful for a widget defining several
classes.

gtk/gtkcssprovider.c

index d61a56417a8fe0fd520f1f9d1c828c85f37c01bf..0c845b20ccb7f9f083af0440bd82bd10ff7ea383 100644 (file)
@@ -1149,7 +1149,7 @@ scanner_apply_scope (GScanner    *scanner,
   else if (scope == SCOPE_SELECTOR)
     {
       scanner->config->cset_identifier_first = G_CSET_a_2_z G_CSET_A_2_Z "*@";
-      scanner->config->cset_identifier_nth = G_CSET_a_2_z "-_#" G_CSET_A_2_Z;
+      scanner->config->cset_identifier_nth = G_CSET_a_2_z "-_#." G_CSET_A_2_Z;
       scanner->config->scan_identifier_1char = TRUE;
     }
   else if (scope == SCOPE_PSEUDO_CLASS ||
@@ -1364,6 +1364,28 @@ parse_pseudo_class (GtkCssProvider *css_provider,
   return G_TOKEN_NONE;
 }
 
+/* Parses a number of concatenated classes */
+static void
+parse_classes (SelectorPath   *path,
+               const gchar    *str)
+{
+  gchar *pos;
+
+  if ((pos = strchr (str, '.')) != NULL)
+    {
+      while (pos)
+        {
+          *pos = '\0';
+          selector_path_prepend_class (path, str);
+
+          str = pos + 1;
+          pos = strchr (str, '.');
+        }
+    }
+  else
+    selector_path_prepend_class (path, str);
+}
+
 static GTokenType
 parse_selector (GtkCssProvider  *css_provider,
                 GScanner        *scanner,
@@ -1388,6 +1410,7 @@ parse_selector (GtkCssProvider  *css_provider,
           scanner->token == '.')
         {
           gboolean is_class;
+          gchar *pos;
 
           is_class = (scanner->token == '.');
 
@@ -1400,9 +1423,18 @@ parse_selector (GtkCssProvider  *css_provider,
           selector_path_prepend_combinator (path, COMBINATOR_CHILD);
 
           if (is_class)
-            selector_path_prepend_class (path, scanner->value.v_identifier);
+            parse_classes (path, scanner->value.v_identifier);
           else
-            selector_path_prepend_name (path, scanner->value.v_identifier);
+            {
+              if ((pos = strchr (scanner->value.v_identifier, '.')) != NULL)
+                *pos = '\0';
+
+              selector_path_prepend_name (path, scanner->value.v_identifier);
+
+              /* Parse any remaining classes */
+              if (pos)
+                parse_classes (path, pos + 1);
+            }
         }
       else if (g_ascii_isupper (scanner->value.v_identifier[0]))
         {
@@ -1429,9 +1461,18 @@ parse_selector (GtkCssProvider  *css_provider,
               selector_path_prepend_combinator (path, COMBINATOR_CHILD);
 
               if (is_class)
-                selector_path_prepend_class (path, name);
+                parse_classes (path, name);
               else
-                selector_path_prepend_name (path, name);
+                {
+                  if ((pos = strchr (name, '.')) != NULL)
+                    *pos = '\0';
+
+                  selector_path_prepend_name (path, name);
+
+                  /* Parse any remaining classes */
+                  if (pos)
+                    parse_classes (path, pos + 1);
+                }
             }
           else
             selector_path_prepend_type (path, scanner->value.v_identifier);